home *** CD-ROM | disk | FTP | other *** search
/ MacAddict 83 / MacAddict_083_2003-07.iso / mac / Software / Development / VLC Source 0.5.3.dmg / src / video_output / vout_pictures.c < prev    next >
C/C++ Source or Header  |  2003-04-07  |  26KB  |  711 lines

  1. /*****************************************************************************
  2.  * vout_pictures.c : picture management functions
  3.  *****************************************************************************
  4.  * Copyright (C) 2000 VideoLAN
  5.  * $Id: vout_pictures.c,v 1.36 2003/03/28 17:02:25 gbazin Exp $
  6.  *
  7.  * Authors: Vincent Seguin <seguin@via.ecp.fr>
  8.  *          Samuel Hocevar <sam@zoy.org>
  9.  *
  10.  * This program is free software; you can redistribute it and/or modify
  11.  * it under the terms of the GNU General Public License as published by
  12.  * the Free Software Foundation; either version 2 of the License, or
  13.  * (at your option) any later version.
  14.  *
  15.  * This program is distributed in the hope that it will be useful,
  16.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18.  * GNU General Public License for more details.
  19.  *
  20.  * You should have received a copy of the GNU General Public License
  21.  * along with this program; if not, write to the Free Software
  22.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
  23.  *****************************************************************************/
  24.  
  25. /*****************************************************************************
  26.  * Preamble
  27.  *****************************************************************************/
  28. #include <stdlib.h>                                                /* free() */
  29. #include <stdio.h>                                              /* sprintf() */
  30. #include <string.h>                                            /* strerror() */
  31.  
  32. #include <vlc/vlc.h>
  33.  
  34. #include "video.h"
  35. #include "video_output.h"
  36.  
  37. #include "vout_pictures.h"
  38.  
  39. /*****************************************************************************
  40.  * Local prototypes
  41.  *****************************************************************************/
  42. static void CopyPicture( vout_thread_t *, picture_t *, picture_t * );
  43.  
  44. /*****************************************************************************
  45.  * vout_DisplayPicture: display a picture
  46.  *****************************************************************************
  47.  * Remove the reservation flag of a picture, which will cause it to be ready for
  48.  * display. The picture won't be displayed until vout_DatePicture has been
  49.  * called.
  50.  *****************************************************************************/
  51. void vout_DisplayPicture( vout_thread_t *p_vout, picture_t *p_pic )
  52. {
  53.     vlc_mutex_lock( &p_vout->picture_lock );
  54.     switch( p_pic->i_status )
  55.     {
  56.     case RESERVED_PICTURE:
  57.         p_pic->i_status = RESERVED_DISP_PICTURE;
  58.         break;
  59.     case RESERVED_DATED_PICTURE:
  60.         p_pic->i_status = READY_PICTURE;
  61.         break;
  62.     default:
  63.         msg_Err( p_vout, "picture to display %p has invalid status %d",
  64.                          p_pic, p_pic->i_status );
  65.         break;
  66.     }
  67.  
  68.     vlc_mutex_unlock( &p_vout->picture_lock );
  69. }
  70.  
  71. /*****************************************************************************
  72.  * vout_DatePicture: date a picture
  73.  *****************************************************************************
  74.  * Remove the reservation flag of a picture, which will cause it to be ready
  75.  * for display. The picture won't be displayed until vout_DisplayPicture has
  76.  * been called.
  77.  *****************************************************************************/
  78. void vout_DatePicture( vout_thread_t *p_vout,
  79.                        picture_t *p_pic, mtime_t date )
  80. {
  81.     vlc_mutex_lock( &p_vout->picture_lock );
  82.     p_pic->date = date;
  83.     switch( p_pic->i_status )
  84.     {
  85.     case RESERVED_PICTURE:
  86.         p_pic->i_status = RESERVED_DATED_PICTURE;
  87.         break;
  88.     case RESERVED_DISP_PICTURE:
  89.         p_pic->i_status = READY_PICTURE;
  90.         break;
  91.     default:
  92.         msg_Err( p_vout, "picture to date %p has invalid status %d",
  93.                          p_pic, p_pic->i_status );
  94.         break;
  95.     }
  96.  
  97.     vlc_mutex_unlock( &p_vout->picture_lock );
  98. }
  99.  
  100. /*****************************************************************************
  101.  * vout_CreatePicture: allocate a picture in the video output heap.
  102.  *****************************************************************************
  103.  * This function creates a reserved image in the video output heap.
  104.  * A null pointer is returned if the function fails. This method provides an
  105.  * already allocated zone of memory in the picture data fields. It needs locking
  106.  * since several pictures can be created by several producers threads.
  107.  *****************************************************************************/
  108. picture_t *vout_CreatePicture( vout_thread_t *p_vout,
  109.                                vlc_bool_t b_progressive,
  110.                                vlc_bool_t b_top_field_first,
  111.                                vlc_bool_t b_repeat_first_field )
  112. {
  113.     int         i_pic;                                      /* picture index */
  114.     picture_t * p_pic;
  115.     picture_t * p_freepic = NULL;                      /* first free picture */
  116.  
  117.     /* Get lock */
  118.     vlc_mutex_lock( &p_vout->picture_lock );
  119.  
  120.     /*
  121.      * Look for an empty place in the picture heap.
  122.      */
  123.     for( i_pic = 0; i_pic < I_RENDERPICTURES; i_pic++ )
  124.     {
  125.         p_pic = PP_RENDERPICTURE[(p_vout->render.i_last_used_pic + i_pic + 1)
  126.                                  % I_RENDERPICTURES];
  127.  
  128.         switch( p_pic->i_status )
  129.         {
  130.             case DESTROYED_PICTURE:
  131.                 /* Memory will not be reallocated, and function can end
  132.                  * immediately - this is the best possible case, since no
  133.                  * memory allocation needs to be done */
  134.                 p_pic->i_status   = RESERVED_PICTURE;
  135.                 p_pic->i_refcount = 0;
  136.                 p_pic->b_force    = 0;
  137.  
  138.                 p_pic->b_progressive        = b_progressive;
  139.                 p_pic->b_repeat_first_field = b_repeat_first_field;
  140.                 p_pic->b_top_field_first    = b_top_field_first;
  141.  
  142.                 p_vout->i_heap_size++;
  143.                 p_vout->render.i_last_used_pic =
  144.                     ( p_vout->render.i_last_used_pic + i_pic + 1 )
  145.                     % I_RENDERPICTURES;
  146.                 vlc_mutex_unlock( &p_vout->picture_lock );
  147.                 return( p_pic );
  148.  
  149.             case FREE_PICTURE:
  150.                 /* Picture is empty and ready for allocation */
  151.                 p_vout->render.i_last_used_pic =
  152.                     ( p_vout->render.i_last_used_pic + i_pic + 1 )
  153.                     % I_RENDERPICTURES;
  154.                 p_freepic = p_pic;
  155.                 break;
  156.  
  157.             default:
  158.                 break;
  159.         }
  160.     }
  161.  
  162.     /*
  163.      * Prepare picture
  164.      */
  165.     if( p_freepic != NULL )
  166.     {
  167.         vout_AllocatePicture( p_vout, p_freepic,
  168.                               p_vout->render.i_width, p_vout->render.i_height,
  169.                               p_vout->render.i_chroma );
  170.  
  171.         if( p_freepic->i_planes )
  172.         {
  173.             /* Copy picture information, set some default values */
  174.             p_freepic->i_status   = RESERVED_PICTURE;
  175.             p_freepic->i_type     = MEMORY_PICTURE;
  176.  
  177.             p_freepic->i_refcount = 0;
  178.             p_freepic->b_force = 0;
  179.  
  180.             p_freepic->b_progressive        = b_progressive;
  181.             p_freepic->b_repeat_first_field = b_repeat_first_field;
  182.             p_freepic->b_top_field_first    = b_top_field_first;
  183.  
  184.             p_freepic->i_matrix_coefficients = 1;
  185.  
  186.             p_vout->i_heap_size++;
  187.         }
  188.         else
  189.         {
  190.             /* Memory allocation failed : set picture as empty */
  191.             p_freepic->i_status = FREE_PICTURE;
  192.             p_freepic = NULL;
  193.  
  194.             msg_Err( p_vout, "picture allocation failed" );
  195.         }
  196.  
  197.         vlc_mutex_unlock( &p_vout->picture_lock );
  198.  
  199.         return( p_freepic );
  200.     }
  201.  
  202.     /* No free or destroyed picture could be found, but the decoder
  203.      * will try again in a while. */
  204.     vlc_mutex_unlock( &p_vout->picture_lock );
  205.  
  206.     return( NULL );
  207. }
  208.  
  209. /*****************************************************************************
  210.  * vout_DestroyPicture: remove a permanent or reserved picture from the heap
  211.  *****************************************************************************
  212.  * This function frees a previously reserved picture or a permanent
  213.  * picture. It is meant to be used when the construction of a picture aborted.
  214.  * Note that the picture will be destroyed even if it is linked !
  215.  *****************************************************************************/
  216. void vout_DestroyPicture( vout_thread_t *p_vout, picture_t *p_pic )
  217. {
  218.     vlc_mutex_lock( &p_vout->picture_lock );
  219.  
  220. #ifdef DEBUG
  221.     /* Check if picture status is valid */
  222.     if( (p_pic->i_status != RESERVED_PICTURE) &&
  223.         (p_pic->i_status != RESERVED_DATED_PICTURE) &&
  224.         (p_pic->i_status != RESERVED_DISP_PICTURE) )
  225.     {
  226.         msg_Err( p_vout, "picture to destroy %p has invalid status %d",
  227.                          p_pic, p_pic->i_status );
  228.     }
  229. #endif
  230.  
  231.     p_pic->i_status = DESTROYED_PICTURE;
  232.     p_vout->i_heap_size--;
  233.  
  234.     vlc_mutex_unlock( &p_vout->picture_lock );
  235. }
  236.  
  237. /*****************************************************************************
  238.  * vout_LinkPicture: increment reference counter of a picture
  239.  *****************************************************************************
  240.  * This function increments the reference counter of a picture in the video
  241.  * heap. It needs a lock since several producer threads can access the picture.
  242.  *****************************************************************************/
  243. void vout_LinkPicture( vout_thread_t *p_vout, picture_t *p_pic )
  244. {
  245.     vlc_mutex_lock( &p_vout->picture_lock );
  246.     p_pic->i_refcount++;
  247.     vlc_mutex_unlock( &p_vout->picture_lock );
  248. }
  249.  
  250. /*****************************************************************************
  251.  * vout_UnlinkPicture: decrement reference counter of a picture
  252.  *****************************************************************************
  253.  * This function decrement the reference counter of a picture in the video heap.
  254.  *****************************************************************************/
  255. void vout_UnlinkPicture( vout_thread_t *p_vout, picture_t *p_pic )
  256. {
  257.     vlc_mutex_lock( &p_vout->picture_lock );
  258.     p_pic->i_refcount--;
  259.  
  260.     if( p_pic->i_refcount < 0 )
  261.     {
  262.         msg_Err( p_vout, "picture refcount is %i", p_pic->i_refcount );
  263.         p_pic->i_refcount = 0;
  264.     }
  265.  
  266.     if( ( p_pic->i_refcount == 0 ) &&
  267.         ( p_pic->i_status == DISPLAYED_PICTURE ) )
  268.     {
  269.         p_pic->i_status = DESTROYED_PICTURE;
  270.         p_vout->i_heap_size--;
  271.     }
  272.  
  273.     vlc_mutex_unlock( &p_vout->picture_lock );
  274. }
  275.  
  276. /*****************************************************************************
  277.  * vout_RenderPicture: render a picture
  278.  *****************************************************************************
  279.  * This function chooses whether the current picture needs to be copied
  280.  * before rendering, does the subpicture magic, and tells the video output
  281.  * thread which direct buffer needs to be displayed.
  282.  *****************************************************************************/
  283. picture_t * vout_RenderPicture( vout_thread_t *p_vout, picture_t *p_pic,
  284.                                                        subpicture_t *p_subpic )
  285. {
  286.     if( p_pic == NULL )
  287.     {
  288.         /* XXX: subtitles */
  289.  
  290.         return NULL;
  291.     }
  292.  
  293.     if( p_pic->i_type == DIRECT_PICTURE )
  294.     {
  295.         if( !p_vout->render.b_allow_modify_pics || p_pic->i_refcount )
  296.         {
  297.             /* Picture is in a direct buffer and is still in use,
  298.              * we need to copy it to another direct buffer before
  299.              * displaying it if there are subtitles. */
  300.             if( p_subpic != NULL )
  301.             {
  302.                 /* We have subtitles. First copy the picture to
  303.                  * the spare direct buffer, then render the
  304.                  * subtitles. */
  305.                 CopyPicture( p_vout, p_pic, PP_OUTPUTPICTURE[0] );
  306.  
  307.                 vout_RenderSubPictures( p_vout, PP_OUTPUTPICTURE[0], p_subpic );
  308.  
  309.                 return PP_OUTPUTPICTURE[0];
  310.             }
  311.  
  312.             /* No subtitles, picture is in a directbuffer so
  313.              * we can display it directly even if it is still
  314.              * in use. */
  315.             return p_pic;
  316.         }
  317.  
  318.         /* Picture is in a direct buffer but isn't used by the
  319.          * decoder. We can safely render subtitles on it and
  320.          * display it. */
  321.         vout_RenderSubPictures( p_vout, p_pic, p_subpic );
  322.  
  323.         return p_pic;
  324.     }
  325.  
  326.     /* Not a direct buffer. We either need to copy it to a direct buffer,
  327.      * or render it if the chroma isn't the same. */
  328.     if( p_vout->b_direct )
  329.     {
  330.         /* Picture is not in a direct buffer, but is exactly the
  331.          * same size as the direct buffers. A memcpy() is enough,
  332.          * then render the subtitles. */
  333.  
  334.         if( PP_OUTPUTPICTURE[0]->pf_lock )
  335.             if( PP_OUTPUTPICTURE[0]->pf_lock( p_vout, PP_OUTPUTPICTURE[0] ) )
  336.             {
  337.                 if( PP_OUTPUTPICTURE[0]->pf_unlock )
  338.                 PP_OUTPUTPICTURE[0]->pf_unlock( p_vout, PP_OUTPUTPICTURE[0] );
  339.  
  340.                 return NULL;
  341.             }
  342.  
  343.         CopyPicture( p_vout, p_pic, PP_OUTPUTPICTURE[0] );
  344.  
  345.         vout_RenderSubPictures( p_vout, PP_OUTPUTPICTURE[0], p_subpic );
  346.  
  347.         if( PP_OUTPUTPICTURE[0]->pf_unlock )
  348.             PP_OUTPUTPICTURE[0]->pf_unlock( p_vout, PP_OUTPUTPICTURE[0] );
  349.  
  350.         return PP_OUTPUTPICTURE[0];
  351.     }
  352.  
  353.     /* Picture is not in a direct buffer, and needs to be converted to
  354.      * another size/chroma. Then the subtitles need to be rendered as
  355.      * well. This usually means software YUV, or hardware YUV with a
  356.      * different chroma. */
  357.  
  358.     if( p_vout->p_picture[0].pf_lock )
  359.         if( p_vout->p_picture[0].pf_lock( p_vout, &p_vout->p_picture[0] ) )
  360.             return NULL;
  361.  
  362.     /* Convert image to the first direct buffer */
  363.     p_vout->chroma.pf_convert( p_vout, p_pic, &p_vout->p_picture[0] );
  364.  
  365.     /* Render subpictures on the first direct buffer */
  366.     vout_RenderSubPictures( p_vout, &p_vout->p_picture[0], p_subpic );
  367.  
  368.     if( p_vout->p_picture[0].pf_unlock )
  369.         p_vout->p_picture[0].pf_unlock( p_vout, &p_vout->p_picture[0] );
  370.  
  371.     return &p_vout->p_picture[0];
  372. }
  373.  
  374. /*****************************************************************************
  375.  * vout_PlacePicture: calculate image window coordinates
  376.  *****************************************************************************
  377.  * This function will be accessed by plugins. It calculates the relative
  378.  * position of the output window and the image window.
  379.  *****************************************************************************/
  380. void vout_PlacePicture( vout_thread_t *p_vout,
  381.                         unsigned int i_width, unsigned int i_height,
  382.                         unsigned int *pi_x, unsigned int *pi_y,
  383.                         unsigned int *pi_width, unsigned int *pi_height )
  384. {
  385.     if( (i_width <= 0) || (i_height <=0) )
  386.     {
  387.         *pi_width = *pi_height = *pi_x = *pi_y = 0;
  388.  
  389.         return;
  390.     }
  391.  
  392.     if( p_vout->b_scale )
  393.     {
  394.         *pi_width = i_width;
  395.         *pi_height = i_height;
  396.     }
  397.     else
  398.     {
  399.         *pi_width = __MIN( i_width, p_vout->render.i_width );
  400.         *pi_height = __MIN( i_height, p_vout->render.i_height );
  401.     }
  402.  
  403.     if( VOUT_ASPECT_FACTOR * *pi_width / *pi_height < p_vout->render.i_aspect )
  404.     {
  405.         *pi_width = *pi_height * p_vout->render.i_aspect / VOUT_ASPECT_FACTOR;
  406.     }
  407.     else
  408.     {
  409.         *pi_height = *pi_width * VOUT_ASPECT_FACTOR / p_vout->render.i_aspect;
  410.     }
  411.  
  412.     if( *pi_width > i_width )
  413.     {
  414.         *pi_width = i_width;
  415.         *pi_height = VOUT_ASPECT_FACTOR * *pi_width / p_vout->render.i_aspect;
  416.     }
  417.  
  418.     if( *pi_height > i_height )
  419.     {
  420.         *pi_height = i_height;
  421.         *pi_width = *pi_height * p_vout->render.i_aspect / VOUT_ASPECT_FACTOR;
  422.     }
  423.  
  424.     *pi_x = ( i_width - *pi_width ) / 2;
  425.     *pi_y = ( i_height - *pi_height ) / 2;
  426. }
  427.  
  428. /*****************************************************************************
  429.  * vout_AllocatePicture: allocate a new picture in the heap.
  430.  *****************************************************************************
  431.  * This function allocates a fake direct buffer in memory, which can be
  432.  * used exactly like a video buffer. The video output thread then manages
  433.  * how it gets displayed.
  434.  *****************************************************************************/
  435. void vout_AllocatePicture( vout_thread_t *p_vout, picture_t *p_pic,
  436.                            int i_width, int i_height, vlc_fourcc_t i_chroma )
  437. {
  438.     int i_bytes, i_index;
  439.  
  440.     /* Store default values */
  441.     for( i_index = 0; i_index < VOUT_MAX_PLANES; i_index++ )
  442.     {
  443.         p_pic->p[i_index].p_pixels = NULL;
  444.         p_pic->p[i_index].i_pixel_pitch = 1;
  445.     }
  446.  
  447.     /* Calculate coordinates */
  448.     switch( i_chroma )
  449.     {
  450.         case FOURCC_I410:
  451.             p_pic->p[ Y_PLANE ].i_lines = i_height;
  452.             p_pic->p[ Y_PLANE ].i_pitch = i_width;
  453.             p_pic->p[ Y_PLANE ].i_visible_pitch = p_pic->p[ Y_PLANE ].i_pitch;
  454.             p_pic->p[ U_PLANE ].i_lines = i_height / 4;
  455.             p_pic->p[ U_PLANE ].i_pitch = i_width / 4;
  456.             p_pic->p[ U_PLANE ].i_visible_pitch = p_pic->p[ U_PLANE ].i_pitch;
  457.             p_pic->p[ V_PLANE ].i_lines = i_height / 4;
  458.             p_pic->p[ V_PLANE ].i_pitch = i_width / 4;
  459.             p_pic->p[ V_PLANE ].i_visible_pitch = p_pic->p[ V_PLANE ].i_pitch;
  460.             p_pic->i_planes = 3;
  461.             break;
  462.  
  463.         case FOURCC_YV12:
  464.         case FOURCC_I420:
  465.         case FOURCC_IYUV:
  466.             p_pic->p[ Y_PLANE ].i_lines = i_height;
  467.             p_pic->p[ Y_PLANE ].i_pitch = i_width;
  468.             p_pic->p[ Y_PLANE ].i_visible_pitch = p_pic->p[ Y_PLANE ].i_pitch;
  469.             p_pic->p[ U_PLANE ].i_lines = i_height / 2;
  470.             p_pic->p[ U_PLANE ].i_pitch = i_width / 2;
  471.             p_pic->p[ U_PLANE ].i_visible_pitch = p_pic->p[ U_PLANE ].i_pitch;
  472.             p_pic->p[ V_PLANE ].i_lines = i_height / 2;
  473.             p_pic->p[ V_PLANE ].i_pitch = i_width / 2;
  474.             p_pic->p[ V_PLANE ].i_visible_pitch = p_pic->p[ V_PLANE ].i_pitch;
  475.             p_pic->i_planes = 3;
  476.             break;
  477.  
  478.         case FOURCC_I422:
  479.             p_pic->p[ Y_PLANE ].i_lines = i_height;
  480.             p_pic->p[ Y_PLANE ].i_pitch = i_width;
  481.             p_pic->p[ Y_PLANE ].i_visible_pitch = p_pic->p[ Y_PLANE ].i_pitch;
  482.             p_pic->p[ U_PLANE ].i_lines = i_height;
  483.             p_pic->p[ U_PLANE ].i_pitch = i_width / 2;
  484.             p_pic->p[ U_PLANE ].i_visible_pitch = p_pic->p[ U_PLANE ].i_pitch;
  485.             p_pic->p[ V_PLANE ].i_lines = i_height;
  486.             p_pic->p[ V_PLANE ].i_pitch = i_width / 2;
  487.             p_pic->p[ V_PLANE ].i_visible_pitch = p_pic->p[ V_PLANE ].i_pitch;
  488.             p_pic->i_planes = 3;
  489.             break;
  490.  
  491.         case FOURCC_I444:
  492.             p_pic->p[ Y_PLANE ].i_lines = i_height;
  493.             p_pic->p[ Y_PLANE ].i_pitch = i_width;
  494.             p_pic->p[ Y_PLANE ].i_visible_pitch = p_pic->p[ Y_PLANE ].i_pitch;
  495.             p_pic->p[ U_PLANE ].i_lines = i_height;
  496.             p_pic->p[ U_PLANE ].i_pitch = i_width;
  497.             p_pic->p[ U_PLANE ].i_visible_pitch = p_pic->p[ U_PLANE ].i_pitch;
  498.             p_pic->p[ V_PLANE ].i_lines = i_height;
  499.             p_pic->p[ V_PLANE ].i_pitch = i_width;
  500.             p_pic->p[ V_PLANE ].i_visible_pitch = p_pic->p[ V_PLANE ].i_pitch;
  501.             p_pic->i_planes = 3;
  502.             break;
  503.  
  504.         case FOURCC_Y211:
  505.             p_pic->p->i_lines = i_height;
  506.             p_pic->p->i_pitch = i_width;
  507.             p_pic->p->i_visible_pitch = p_pic->p->i_pitch;
  508.             p_pic->p->i_pixel_pitch = 4;
  509.             p_pic->i_planes = 1;
  510.             break;
  511.  
  512.         case FOURCC_YUY2:
  513.             p_pic->p->i_lines = i_height;
  514.             p_pic->p->i_pitch = i_width * 2;
  515.             p_pic->p->i_visible_pitch = p_pic->p->i_pitch;
  516.             p_pic->p->i_pixel_pitch = 4;
  517.             p_pic->i_planes = 1;
  518.             break;
  519.  
  520.         case FOURCC_RGB2:
  521.             p_pic->p->i_lines = i_height;
  522.             p_pic->p->i_pitch = i_width;
  523.             p_pic->p->i_visible_pitch = p_pic->p->i_pitch;
  524.             p_pic->p->i_pixel_pitch = 1;
  525.             p_pic->i_planes = 1;
  526.             break;
  527.  
  528.         case FOURCC_RV15:
  529.             p_pic->p->i_lines = i_height;
  530.             p_pic->p->i_pitch = i_width * 2;
  531.             p_pic->p->i_visible_pitch = p_pic->p->i_pitch;
  532.             p_pic->p->i_pixel_pitch = 2;
  533. /* FIXME: p_heap isn't always reachable
  534.             p_pic->p_heap->i_rmask = 0x001f;
  535.             p_pic->p_heap->i_gmask = 0x03e0;
  536.             p_pic->p_heap->i_bmask = 0x7c00; */
  537.             p_pic->i_planes = 1;
  538.             break;
  539.  
  540.         case FOURCC_RV16:
  541.             p_pic->p->i_lines = i_height;
  542.             p_pic->p->i_pitch = i_width * 2;
  543.             p_pic->p->i_visible_pitch = p_pic->p->i_pitch;
  544.             p_pic->p->i_pixel_pitch = 2;
  545. /* FIXME: p_heap isn't always reachable
  546.             p_pic->p_heap->i_rmask = 0x001f;
  547.             p_pic->p_heap->i_gmask = 0x07e0;
  548.             p_pic->p_heap->i_bmask = 0xf800; */
  549.             p_pic->i_planes = 1;
  550.             break;
  551.  
  552.         case FOURCC_RV24:
  553.             p_pic->p->i_lines = i_height;
  554.             p_pic->p->i_pitch = i_width * 3;
  555.             p_pic->p->i_visible_pitch = p_pic->p->i_pitch;
  556.             p_pic->p->i_pixel_pitch = 3;
  557. /* FIXME: p_heap isn't always reachable
  558.             p_pic->p_heap->i_rmask = 0xff0000;
  559.             p_pic->p_heap->i_gmask = 0x00ff00;
  560.             p_pic->p_heap->i_bmask = 0x0000ff; */
  561.             p_pic->i_planes = 1;
  562.             break;
  563.  
  564.         case FOURCC_RV32:
  565.             p_pic->p->i_lines = i_height;
  566.             p_pic->p->i_pitch = i_width * 4;
  567.             p_pic->p->i_visible_pitch = p_pic->p->i_pitch;
  568.             p_pic->p->i_pixel_pitch = 4;
  569. /* FIXME: p_heap isn't always reachable
  570.             p_pic->p_heap->i_rmask = 0xff0000;
  571.             p_pic->p_heap->i_gmask = 0x00ff00;
  572.             p_pic->p_heap->i_bmask = 0x0000ff; */
  573.             p_pic->i_planes = 1;
  574.             break;
  575.  
  576.         default:
  577.             msg_Err( p_vout, "unknown chroma type 0x%.8x (%4.4s)",
  578.                              i_chroma, (char*)&i_chroma );
  579.             p_pic->i_planes = 0;
  580.             return;
  581.     }
  582.  
  583.     /* Calculate how big the new image should be */
  584.     for( i_bytes = 0, i_index = 0; i_index < p_pic->i_planes; i_index++ )
  585.     {
  586.         i_bytes += p_pic->p[ i_index ].i_lines * p_pic->p[ i_index ].i_pitch;
  587.     }
  588.  
  589.     p_pic->p_data = vlc_memalign( &p_pic->p_data_orig, 16, i_bytes );
  590.  
  591.     if( p_pic->p_data == NULL )
  592.     {
  593.         p_pic->i_planes = 0;
  594.         return;
  595.     }
  596.  
  597.     /* Fill the p_pixels field for each plane */
  598.     p_pic->p[ 0 ].p_pixels = p_pic->p_data;
  599.  
  600.     for( i_index = 1; i_index < p_pic->i_planes; i_index++ )
  601.     {
  602.         p_pic->p[i_index].p_pixels = p_pic->p[i_index-1].p_pixels
  603.                                           + p_pic->p[i_index-1].i_lines
  604.                                              * p_pic->p[i_index-1].i_pitch;
  605.     }
  606. }
  607.  
  608. /*****************************************************************************
  609.  * vout_ChromaCmp: compare two chroma values
  610.  *****************************************************************************
  611.  * This function returns 1 if the two fourcc values given as argument are
  612.  * the same format (eg. UYVY / UYNV) or almost the same format (eg. I420/YV12)
  613.  *****************************************************************************/
  614. int vout_ChromaCmp( vlc_fourcc_t i_chroma, vlc_fourcc_t i_amorhc )
  615. {
  616.     /* If they are the same, they are the same ! */
  617.     if( i_chroma == i_amorhc )
  618.     {
  619.         return 1;
  620.     }
  621.  
  622.     /* Check for equivalence classes */
  623.     switch( i_chroma )
  624.     {
  625.         case FOURCC_I420:
  626.         case FOURCC_IYUV:
  627.         case FOURCC_YV12:
  628.             switch( i_amorhc )
  629.             {
  630.                 case FOURCC_I420:
  631.                 case FOURCC_IYUV:
  632.                 case FOURCC_YV12:
  633.                     return 1;
  634.  
  635.                 default:
  636.                     return 0;
  637.             }
  638.  
  639.         case FOURCC_UYVY:
  640.         case FOURCC_UYNV:
  641.         case FOURCC_Y422:
  642.             switch( i_amorhc )
  643.             {
  644.                 case FOURCC_UYVY:
  645.                 case FOURCC_UYNV:
  646.                 case FOURCC_Y422:
  647.                     return 1;
  648.  
  649.                 default:
  650.                     return 0;
  651.             }
  652.  
  653.         case FOURCC_YUY2:
  654.         case FOURCC_YUNV:
  655.             switch( i_amorhc )
  656.             {
  657.                 case FOURCC_YUY2:
  658.                 case FOURCC_YUNV:
  659.                     return 1;
  660.  
  661.                 default:
  662.                     return 0;
  663.             }
  664.  
  665.         default:
  666.             return 0;
  667.     }
  668. }
  669.  
  670. /* Following functions are local */
  671.  
  672. /*****************************************************************************
  673.  * CopyPicture: copy a picture to another one
  674.  *****************************************************************************
  675.  * This function takes advantage of the image format, and reduces the
  676.  * number of calls to memcpy() to the minimum. Source and destination
  677.  * images must have same width (hence i_visible_pitch), height, and chroma.
  678.  *****************************************************************************/
  679. static void CopyPicture( vout_thread_t * p_vout,
  680.                          picture_t *p_src, picture_t *p_dest )
  681. {
  682.     int i;
  683.  
  684.     for( i = 0; i < p_src->i_planes ; i++ )
  685.     {
  686.         if( p_src->p[i].i_pitch == p_dest->p[i].i_pitch )
  687.         {
  688.             /* There are margins, but with the same width : perfect ! */
  689.             p_vout->p_vlc->pf_memcpy(
  690.                          p_dest->p[i].p_pixels, p_src->p[i].p_pixels,
  691.                          p_src->p[i].i_pitch * p_src->p[i].i_lines );
  692.         }
  693.         else
  694.         {
  695.             /* We need to proceed line by line */
  696.             uint8_t *p_in = p_src->p[i].p_pixels;
  697.             uint8_t *p_out = p_dest->p[i].p_pixels;
  698.             int i_line;
  699.  
  700.             for( i_line = p_src->p[i].i_lines; i_line--; )
  701.             {
  702.                 p_vout->p_vlc->pf_memcpy( p_out, p_in,
  703.                                           p_src->p[i].i_visible_pitch );
  704.                 p_in += p_src->p[i].i_pitch;
  705.                 p_out += p_dest->p[i].i_pitch;
  706.             }
  707.         }
  708.     }
  709.     p_dest->date = p_src->date;
  710. }
  711.